home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
tex
/
dvivga9.arc
/
OPENFONT.H
< prev
next >
Wrap
C/C++ Source or Header
|
1988-05-30
|
11KB
|
325 lines
/* -*-C-*- openfont.h */
/*-->openfont*/
/**********************************************************************/
/****************************** openfont ******************************/
/**********************************************************************/
void
openfont(fontname)
char *fontname;
/***********************************************************************
The original version of this DVI driver reopened the font file each
time the font changed, resulting in an enormous number of relatively
expensive file openings. This version keeps a cache of up to
MAXOPEN open files, so that when a font change is made, the file
pointer, fontfp, can usually be updated from the cache. When the
file is not found in the cache, it must be opened. In this case,
the next empty slot in the cache is assigned, or if the cache is
full, the least used font file is closed and its slot reassigned for
the new file. Identification of the least used file is based on the
counts of the number of times each file has been "opened" by this
routine. On return, the file pointer is always repositioned to the
beginning of the file.
If the first open attempt fails, an attempt will be made to use a
substitute font, then neighboring magnifications (with the same font
name), or substitutes for them.
***********************************************************************/
{
register INT16 i,j,k; /* loop indices */
INT16 current;
INT16 least_used;
INT16 maxopen = MAXOPEN;
#if OS_VAXVMS
long *jpi;
#endif
struct font_entry *tfontptr;
char subfont[MAXFNAME];
int submag;
char* filelist[MAXFORMATS]; /* pointers to templist[][] */
char templist[MAXFORMATS][MAXFNAME];
#if VIRTUAL_FONTS
struct stat statbuf; /* so fstat() can get file size */
char *p;
#endif
if ((pfontptr != (struct font_entry *)NULL) && (pfontptr == fontptr))
return; /* we need not have been called */
for (j = 0; j < MAXFORMATS; ++j) /* initialize fontlist pointers */
filelist[j] = &templist[j][0];
#if IBM_PC_MICROSOFT
/* This code required rewriting to get around a fatal compiler
assertion error occasioned by the code in the #else part */
for (current = 1; current <= nopen; ++current)
{
FILE* pfp;
pfp = font_files[current].font_id;
if (pfp == fontptr->font_file_id)
break;
}
#else
for (current = 1;
(current <= nopen) &&
(font_files[current].font_id != fontptr->font_file_id);
++current)
; /* try to find file in open list */
#endif
if (current <= nopen) /* file already open, lookup its id */
fontfp = font_files[current].font_id;
else
{
/***************************************************************
The file was not in list of open files. If the list is not
full, add it to the list; otherwise close the least-used file
and remove it from the font_entry containing it. Finally, open
the file, or its closest neighbor in the magnification family.
A warning is issued if no file can be opened. The caller can
then proceed with zero font metrics if desired.
***************************************************************/
#if OS_VAXVMS
/***************************************************************
VAX VMS has many user quotas, one of which is the maximum number
of files that can be open, which need have no relation to the
number that C permits. If we do not determine the limit at
run-time, the drivers may attempt to open too many files, and in
such a case, will fail. There are two relevant quotas, FILLM
(open file limit), and FILCNT (remaining open file quota). We
use the latter, and leave one available file for a possible
error log.
***************************************************************/
jpi = (long*)getjpi(JPI$_FILCNT);
if (jpi == (long*)NULL)
maxopen = MAXOPEN; /* should never happen */
else
maxopen = nopen - 1 + *jpi;
maxopen = MIN(maxopen,MAXOPEN); /* we have arrays of size MAXFONT */
/* so do not exceed that limit */
#endif /* OS_VAXVMS */
if (nopen < maxopen) /* just add it to list */
current = ++nopen;
else /* list full -- find least used file, */
{ /* close it, and reuse slot for new file */
least_used = 1;
for (i = 2; i <= maxopen; ++i)
if (font_files[least_used].use_count >
font_files[i].use_count)
least_used = i;
fontfp = font_files[least_used].font_id;
tfontptr = hfontptr;
while (tfontptr != (struct font_entry*)NULL)
{ /* remove file pointer from its font_entry */
if (tfontptr->font_file_id == fontfp)
{
tfontptr->font_file_id = (FILE*)NULL;
break;
}
tfontptr = tfontptr->next;
}
#if VIRTUAL_FONTS
if (virt_font && (fontfp != (FILE*)NULL))
(void)virtfree(fontfp);
#endif
(void)fclose(fontfp);
fontfp = (FILE*)NULL;
current = least_used;
}
(void)actfact(fontptr->font_mag); /* Get global mag_index */
fontfp = (FILE*)NULL;
/***************************************************************
Try the requested font, then any substitute font, then for each
neighboring magnification from nearest to furthest, try the
requested font, and then any substitute font.
***************************************************************/
for (k = 0; (fontfp == (FILE*)NULL) && (k < MAGTABSIZE); ++k)
{ /* loop over mag family */
for (i = -k; (fontfp == (FILE*)NULL) && (i <= k); i += MAX(1,k+k))
{ /* try smaller, then larger */
if (IN(0,mag_index+i,MAGTABSIZE-1))
{
(void)fontfile(filelist, ((fontptr->a==0)?fontpath:""),
fontname, (int)MAGSIZE(mag_table[mag_index+i]));
for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
{
fontfp = FOPEN(filelist[j],RB_OPEN);
DEBUG_OPEN(fontfp,filelist[j],RB_OPEN);
if (fontfp != (FILE *)NULL)
{
strcpy(fontptr->name,filelist[j]);
break;
}
}
if ((k > 0) && (fontfp != (FILE*)NULL))
{
(void)sprintf(message,
"Font file [%s [mag %d]] could not be opened.\n\
---using nearest neighbor [%s [mag %d]] instead.",
fontname,(int)MAGSIZE(mag_table[mag_index]),
fontptr->name,
(int)MAGSIZE(mag_table[mag_index+i]));
(void)warning(message);
}
if ((fontfp == (FILE*)NULL) && fontsub(subfont,&submag,
fontname,(int)MAGSIZE(mag_table[mag_index+i])))
{
(void)fontfile(filelist,((fontptr->a==0)?fontpath:""),
subfont,(submag ? submag :
(int)MAGSIZE(mag_table[mag_index+i])));
for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
{
fontfp = FOPEN(filelist[j],RB_OPEN);
DEBUG_OPEN(fontfp,filelist[j],RB_OPEN);
if (fontfp != (FILE *)NULL)
{
strcpy(fontptr->name,filelist[j]);
break;
}
}
if (fontfp != (FILE*)NULL)
{
(void)sprintf(message,
"Substituting font file [%s [mag %d]] \
by [%s [mag %d]]",
fontname,(int)MAGSIZE(mag_table[mag_index]),
fontptr->name,
(int)MAGSIZE(mag_table[mag_index+i]));
(void)warning(message);
}
}
}
} /* end for (i) -- loop over smaller and larger neighbors */
} /* end for (k) -- loop over mag family */
if (fontfp == (FILE*)NULL)
{
--nopen; /* don't count this failed open */
(void)sprintf(message,"Font file [%s [mag %d]] could not be \
opened; %d font files are open\n\
Proceeding with zero size characters for this font",
fontname,(int)MAGSIZE(mag_table[mag_index]),nopen);
(void)warning(message);
}
font_files[current].font_id = fontfp;
font_files[current].use_count = 0;
#if VIRTUAL_FONTS
/*
****************************************************************
This code is implementation-dependent. On many C compilers,
FILE points to a struct of the form
struct _iobuf {
char *_ptr; // pointer to next available char
int _cnt; // number of chars left in buffer
char *_base; // pointer to start of buffer
int _flag; // assorted flags
int _file; // file number handle
}
To implement virtual fonts, we save the pointers in a private
global array, get the file size from fstat(), malloc() a buffer
for it, read the entire file in, and replace the pointers in the
FILE variable with ones for the new buffer. Just before the
file is closed, the space is freed and the old pointers are
restored. Although many C implementations use malloc() to get
the buffer space in the first place, which would make this
saving unnecessary, not all do; see the implementation given in
Kernighan and Ritchie "The C Programming Language", p. 168.
In implementing this code on any new machine, the
implementations of fread(), read(), fseek(), and rewind() should
be checked to choose the most efficient one (e.g. one system
call for entire file read, and no double buffering), and make
sure that fseek() and rewind() do not unnecessarily discard
input buffer contents. fseek() and rewind() are defined in
terms of macros FSEEK() and REWIND() in machdefs.h to facilitate
replacement.
****************************************************************
*/
if (virt_font)
{
virt_save[fileno(fontfp)].base = (char *)NULL;
(void)fstat(fileno(fontfp),&statbuf); /* get file size */
p = (char *)MALLOC((int)statbuf.st_size); /* get file buffer */
if (p != (char *)NULL)
{
if (READ(fileno(fontfp),p,(int)statbuf.st_size)
== (int)statbuf.st_size)
{ /* read successful */
virt_save[fileno(fontfp)].ptr = FILE_PTR(fontfp);
virt_save[fileno(fontfp)].cnt = FILE_CNT(fontfp);
virt_save[fileno(fontfp)].base = FILE_BASE(fontfp);
FILE_PTR(fontfp) = p;
FILE_BASE(fontfp) = p;
FILE_CNT(fontfp) = (int)statbuf.st_size;
}
else /* failure */
{
(void)REWIND(fontfp);
(void)free(p); /* free dynamic buffer */
}
}
if (DBGOPT(DBG_FONT_CACHE))
{
(void)fprintf(stderr,"\nopenfont(): Font file %d [%s] ",
(int)fileno(fontfp),fontptr->name);
if (p == (char *)NULL)
(void)fprintf(stderr,
"cannot callocate buffer for entire file\n");
else
(void)fprintf(stderr,
"buffer length 0x%x\told buffer at 0x%lx\t\
new buffer at 0x%lx\n",
(int)statbuf.st_size,
(long)virt_save[fileno(fontfp)].base,
(long)FILE_BASE(fontfp));
}
}
#endif
} /* end if (file is in open list) */
pfontptr = fontptr; /* make previous = current font */
fontptr->font_file_id = fontfp; /* set file identifier */
font_files[current].use_count++; /* update reference count */
}
#if VIRTUAL_FONTS
void
virtfree(fp) /* free buffer space before close */
FILE *fp;
{
if (virt_font && (fp != (FILE*)NULL) &&
(virt_save[fileno(fp)].base != (char *)NULL))
{
(void)fflush(fp);
(void)free(FILE_BASE(fp));
FILE_PTR(fp) = virt_save[fileno(fp)].ptr;
FILE_CNT(fp) = virt_save[fileno(fp)].cnt;
FILE_BASE(fp) = virt_save[fileno(fp)].base;
virt_save[fileno(fp)].base = (char *)NULL;
}
}
#endif